/******************************************************************************
 Copyright (c) 2022 - 2024 Qualcomm Technologies International, Ltd.
 All Rights Reserved.
 Qualcomm Technologies International, Ltd. Confidential and Proprietary.

 REVISION:      $Revision: #15 $
******************************************************************************/

#include "csr_synergy.h"

#ifndef EXCLUDE_GATT_XPAN_SERVER_MODULE

#define TRAPSET_MARSHAL 1
#include "service_handle.h"
#include "gatt_xpan_server_private.h"
#include "gatt_xpan_server_handover_mgr.h"
#include "gatt_xpan_server_debug.h"
#include "csr_bt_core_stack_pmalloc.h"

#include <stdlib.h>
#include <panic.h>
#include <marshal.h>

#include <message.h>
#include "marshal_common_desc.h"

/**************************** Start of Desc code ******************************/
#define XPAN_MARSHAL_TYPES_TABLE(ENTRY) \
    ENTRY(StoredSsid) \
    ENTRY(SsidData) \
    ENTRY(SsidData_dyn_arr_t) \
    ENTRY(Ipv4AddressData_dyn_arr_t) \
    ENTRY(Ipv4AddressData) \
    ENTRY(Ipv4Ssid) \
    ENTRY(Ipv4Ssid_dyn_arr_t) \
    ENTRY(Ipv4Address) \
    ENTRY(Ipv6AddressData_dyn_arr_t) \
    ENTRY(Ipv6AddressData) \
    ENTRY(Ipv6Ssid) \
    ENTRY(Ipv6Ssid_dyn_arr_t) \
    ENTRY(Ipv6Address) \
    ENTRY(ConnectedDevicesData) \
    ENTRY(ConnectedDevicesData_dyn_arr_t) \
    ENTRY(ConnectedDevices) \
    ENTRY(MacAddressData) \
    ENTRY(MacAddressData_dyn_arr_t) \
    ENTRY(MacAddress) \
    ENTRY(TwtConfiguration) \
    ENTRY(GattXpanServerConfig)\
    ENTRY(GattXpanHandoverData)


/********************************************************************
 * Enum of 'type' identifiers used for marshalling, of the form MARSHAL_TYPE_xyz
 ********************************************************************/

/* Use xmacro to expand type table as enumeration of marshal types */
#define EXPAND_AS_ENUMERATION(type) MARSHAL_TYPE(type),
enum
{
      COMMON_MARSHAL_TYPES_TABLE(EXPAND_AS_ENUMERATION)
      COMMON_DYN_MARSHAL_TYPES_TABLE(EXPAND_AS_ENUMERATION)
      XPAN_MARSHAL_TYPES_TABLE(EXPAND_AS_ENUMERATION)
      XPAN_MARSHAL_OBJ_TYPE_COUNT
};
#undef EXPAND_AS_ENUMERATION
/*
enum
{
    MARSHAL_TYPE_int,
    MARSHAL_TYPE_int16,
    MARSHAL_TYPE_uint8,
    MARSHAL_TYPE_uint16,
    MARSHAL_TYPE_uint32,
    MARSHAL_TYPE_bdaddr,
    MARSHAL_TYPE_typed_bdaddr,
    MARSHAL_TYPE_TRANSPORT_T,
    MARSHAL_TYPE_tp_bdaddr,
    MARSHAL_TYPE_L2capSink,
    MARSHAL_TYPE_uint8_dyn_arr_t,
    MARSHAL_TYPE_StoredSsid,
    MARSHAL_TYPE_SsidData,
    MARSHAL_TYPE_SsidData_dyn_arr_t,
    MARSHAL_TYPE_Ipv4AddressData_dyn_arr_t,
    MARSHAL_TYPE_Ipv4AddressData,
    MARSHAL_TYPE_Ipv4Ssid,
    MARSHAL_TYPE_Ipv4Ssid_dyn_arr_t,
    MARSHAL_TYPE_Ipv4Address,
    MARSHAL_TYPE_Ipv6AddressData_dyn_arr_t,
    MARSHAL_TYPE_Ipv6AddressData,
    MARSHAL_TYPE_Ipv6Ssid,
    MARSHAL_TYPE_Ipv6Ssid_dyn_arr_t,
    MARSHAL_TYPE_Ipv6Address,
    MARSHAL_TYPE_ConnectedDevicesData,
    MARSHAL_TYPE_ConnectedDevicesData_dyn_arr_t,
    MARSHAL_TYPE_ConnectedDevices,
    MARSHAL_TYPE_MacAddressData,
    MARSHAL_TYPE_MacAddressData_dyn_arr_t,
    MARSHAL_TYPE_MacAddress,
    MARSHAL_TYPE_TwtConfiguration,
    MARSHAL_TYPE_GattXpanServerConfig
    MARSHAL_TYPE_GattXpanHandoverData,
};
*/

/********************************************************************
 * Marshal Descriptors for GattXpanServerConfig
 ********************************************************************/
static const marshal_type_descriptor_t mtd_GattXpanServerConfig =
    MAKE_MARSHAL_TYPE_DEFINITION_BASIC(GattXpanServerConfig);

/********************************************************************
 * Marshal Descriptors for SsidData
 ********************************************************************/
static uint32 getSsidLength(const void *parent,
                            const marshal_member_descriptor_t *memberDescriptor,
                            uint32 arrayElement)
{
    const SsidData *obj = parent;

    PanicFalse(obj && memberDescriptor);
    PanicFalse(arrayElement == 0);
    PanicFalse(memberDescriptor->offset == offsetof(SsidData, ssid));

    return obj->ssidLength;
}

static const marshal_member_descriptor_t mmd_SsidData[] =
{
    MAKE_MARSHAL_MEMBER(SsidData, uint8, ssidLength),
    MAKE_MARSHAL_MEMBER_POINTER(SsidData, uint8_dyn_arr_t, ssid),
};

static const marshal_type_descriptor_dynamic_t mtd_SsidData =
    MAKE_MARSHAL_TYPE_DEFINITION_HAS_PTR_TO_DYNAMIC_ARRAY(
        SsidData,
        mmd_SsidData,
        getSsidLength);

/********************************************************************
 * Marshal Descriptors for SsidData_dyn_arr_t
 ********************************************************************/

/* Dummy type to describe the dynamic array of SsidData */
typedef struct SsidData_dyn_arr
{
    SsidData array[1];
} SsidData_dyn_arr_t;

/* Member descriptors for the dynamic array */
static const marshal_member_descriptor_t mmd_SsidData_dyn_arr_t[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(SsidData_dyn_arr_t, SsidData, array, 1),
};

/* Since SsidData_dyn_arr_t doesn't know the length of its array (only its parent
   knows) a callback is not set. The parent's array_elements callback
   will be called instead. */
const marshal_type_descriptor_dynamic_t mtd_SsidData_dyn_arr_t =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_DYNAMIC_ARRAY(SsidData_dyn_arr_t,
                                                       mmd_SsidData_dyn_arr_t,
                                                       NULL);

/********************************************************************
 * Marshal Descriptors for StoredSsid
 ********************************************************************/

static uint32 getNumSsids(const void *parent,
                          const marshal_member_descriptor_t *memberDescriptor,
                          uint32 arrayElement)
{
    const StoredSsid *obj = parent;
    uint32 len = 0;

    PanicFalse(obj && memberDescriptor);
    PanicFalse(arrayElement == 0);
    PanicFalse(memberDescriptor->offset == offsetof(StoredSsid, ssid));

    len = obj->numSsid;

    return len;
}

static const marshal_member_descriptor_t mmd_StoredSsid[] =
{
    MAKE_MARSHAL_MEMBER(StoredSsid, uint8, numSsid),
    MAKE_MARSHAL_MEMBER_POINTER(StoredSsid, SsidData_dyn_arr_t, ssid),
};

static const marshal_type_descriptor_dynamic_t mtd_StoredSsid =
    MAKE_MARSHAL_TYPE_DEFINITION_HAS_PTR_TO_DYNAMIC_ARRAY(
        StoredSsid,
        mmd_StoredSsid,
        getNumSsids
);

/********************************************************************
 * Marshal Descriptors for Ipv4AddressData
 ********************************************************************/

static const marshal_member_descriptor_t mmd_Ipv4AddressData[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv4AddressData, uint8, ipv4Address, 4),
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv4AddressData, uint8, macAddress, 6),
    MAKE_MARSHAL_MEMBER(Ipv4AddressData, uint32, audioLocation),
    MAKE_MARSHAL_MEMBER(Ipv4AddressData, uint8, role),
    MAKE_MARSHAL_MEMBER(Ipv4AddressData, uint8, status),
};

static const marshal_type_descriptor_t mtd_Ipv4AddressData =
        MAKE_MARSHAL_TYPE_DEFINITION(
        Ipv4AddressData,
        mmd_Ipv4AddressData
);

/********************************************************************
 * Marshal Descriptors for Ipv4AddressData_dyn_arr_t
 ********************************************************************/

/* Dummy type to describe the dynamic array of SsidData */
typedef struct Ipv4AddressData_dyn_arr
{
    Ipv4AddressData array[1];
} Ipv4AddressData_dyn_arr_t;

/* Member descriptors for the dynamic array */
static const marshal_member_descriptor_t mmd_Ipv4AddressData_dyn_arr_t[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv4AddressData_dyn_arr_t, Ipv4AddressData, array, 1),
};

/* Since Ipv4AddressData_dyn_arr_t doesn't know the length of its array (only its parent
   knows) a callback is not set. The parent's array_elements callback
   will be called instead. */
const marshal_type_descriptor_dynamic_t mtd_Ipv4AddressData_dyn_arr_t =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_DYNAMIC_ARRAY(Ipv4AddressData_dyn_arr_t,
                                                       mmd_Ipv4AddressData_dyn_arr_t,
                                                       NULL);

/********************************************************************
 * Marshal Descriptors for Ipv4Ssid
 ********************************************************************/

static uint32 getNumIpv4Addresses(const void *parent,
                                  const marshal_member_descriptor_t *memberDescriptor,
                                  uint32 arrayElement)
{
    const Ipv4Ssid *obj = parent;
    uint32 len = 0;

    PanicFalse(obj && memberDescriptor);
    PanicFalse(arrayElement == 0);
    PanicFalse(memberDescriptor->offset == offsetof(Ipv4Ssid, ipv4Addresses));

    len = obj->numIpv4Addresses;

    return len;
}

static const marshal_member_descriptor_t mmd_Ipv4Ssid[] =
{
    MAKE_MARSHAL_MEMBER(Ipv4Ssid, SsidData, ipv4Ssid),
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv4Ssid, uint8, bssid, 6),
    MAKE_MARSHAL_MEMBER(Ipv4Ssid, uint8, numIpv4Addresses),
    MAKE_MARSHAL_MEMBER_POINTER(Ipv4Ssid, Ipv4AddressData_dyn_arr_t, ipv4Addresses),
};

static const marshal_type_descriptor_dynamic_t mtd_Ipv4Ssid =
    MAKE_MARSHAL_TYPE_DEFINITION_HAS_PTR_TO_DYNAMIC_ARRAY(
            Ipv4Ssid,
        mmd_Ipv4Ssid,
        getNumIpv4Addresses
);

/********************************************************************
 * Marshal Descriptors for Ipv4Ssid_dyn_arr (used in Ipv4Address)
 ********************************************************************/

/* Dummy type to describe the dynamic array of Ipv4Ssid */
typedef struct Ipv4Ssid_dyn_arr
{
    Ipv4Ssid array[1];
} Ipv4Ssid_dyn_arr_t;

/* Member descriptors for the dynamic array */
static const marshal_member_descriptor_t mmd_Ipv4Ssid_dyn_arr_t[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv4Ssid_dyn_arr_t, Ipv4Ssid, array, 1),
};

/* Since SsidData_dyn_arr_t doesn't know the length of its array (only its parent
   knows) a callback is not set. The parent's array_elements callback
   will be called instead. */
const marshal_type_descriptor_dynamic_t mtd_Ipv4Ssid_dyn_arr_t =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_DYNAMIC_ARRAY(Ipv4Ssid_dyn_arr_t,
                                                       mmd_Ipv4Ssid_dyn_arr_t,
                                                       NULL);

/********************************************************************
 * Marshal Descriptors for Ipv4Address
 ********************************************************************/

static uint32 getNumIpv4Ssids(const void *parent,
                                  const marshal_member_descriptor_t *memberDescriptor,
                                  uint32 arrayElement)
{
    const Ipv4Address *obj = parent;
    uint32 len = 0;

    PanicFalse(obj && memberDescriptor);
    PanicFalse(arrayElement == 0);
    PanicFalse(memberDescriptor->offset == offsetof(Ipv4Address, ipv4Ssids));

    len = obj->numSsids;

    return len;
}

static const marshal_member_descriptor_t mmd_Ipv4Address[] =
{
    MAKE_MARSHAL_MEMBER(Ipv4Address, uint8, numSsids),
    MAKE_MARSHAL_MEMBER_POINTER(Ipv4Address, Ipv4Ssid_dyn_arr_t, ipv4Ssids),
};

static const marshal_type_descriptor_dynamic_t mtd_Ipv4Address =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_PTR_TO_DYNAMIC_ARRAY(
                Ipv4Address,
            mmd_Ipv4Address,
            getNumIpv4Ssids
);

/********************************************************************
 * Marshal Descriptors for Ipv6AddressData
 ********************************************************************/

static const marshal_member_descriptor_t mmd_Ipv6AddressData[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv6AddressData, uint8, ipv6Address, 16),
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv6AddressData, uint8, macAddress, 6),
    MAKE_MARSHAL_MEMBER(Ipv6AddressData, uint32, audioLocation),
    MAKE_MARSHAL_MEMBER(Ipv6AddressData, uint8, role),
    MAKE_MARSHAL_MEMBER(Ipv6AddressData, uint8, status),
};

static const marshal_type_descriptor_t mtd_Ipv6AddressData =
        MAKE_MARSHAL_TYPE_DEFINITION(
        Ipv6AddressData,
        mmd_Ipv6AddressData
);

/********************************************************************
 * Marshal Descriptors for Ipv6AddressData_dyn_arr_t
 ********************************************************************/

/* Dummy type to describe the dynamic array of SsidData */
typedef struct Ipv6AddressData_dyn_arr
{
    Ipv6AddressData array[1];
} Ipv6AddressData_dyn_arr_t;

/* Member descriptors for the dynamic array */
static const marshal_member_descriptor_t mmd_Ipv6AddressData_dyn_arr_t[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv6AddressData_dyn_arr_t, Ipv6AddressData, array, 1),
};

/* Since Ipv6AddressData_dyn_arr_t doesn't know the length of its array (only its parent
   knows) a callback is not set. The parent's array_elements callback
   will be called instead. */
const marshal_type_descriptor_dynamic_t mtd_Ipv6AddressData_dyn_arr_t =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_DYNAMIC_ARRAY(Ipv6AddressData_dyn_arr_t,
                                                       mmd_Ipv6AddressData_dyn_arr_t,
                                                       NULL);

/********************************************************************
 * Marshal Descriptors for Ipv6Ssid
 ********************************************************************/

static uint32 getNumIpv6Addresses(const void *parent,
                                  const marshal_member_descriptor_t *memberDescriptor,
                                  uint32 arrayElement)
{
    const Ipv6Ssid *obj = parent;
    uint32 len = 0;

    PanicFalse(obj && memberDescriptor);
    PanicFalse(arrayElement == 0);
    PanicFalse(memberDescriptor->offset == offsetof(Ipv6Ssid, ipv6Addresses));

    len = obj->numIpv6Addresses;

    return len;
}

static const marshal_member_descriptor_t mmd_Ipv6Ssid[] =
{
    MAKE_MARSHAL_MEMBER(Ipv6Ssid, SsidData, ipv6Ssid),
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv6Ssid, uint8, bssid, 6),
    MAKE_MARSHAL_MEMBER(Ipv6Ssid, uint8, numIpv6Addresses),
    MAKE_MARSHAL_MEMBER_POINTER(Ipv6Ssid, Ipv6AddressData_dyn_arr_t, ipv6Addresses),
};

static const marshal_type_descriptor_dynamic_t mtd_Ipv6Ssid =
    MAKE_MARSHAL_TYPE_DEFINITION_HAS_PTR_TO_DYNAMIC_ARRAY(
            Ipv6Ssid,
        mmd_Ipv6Ssid,
        getNumIpv6Addresses
);

/********************************************************************
 * Marshal Descriptors for Ipv6Ssid_dyn_arr (used in Ipv6Address)
 ********************************************************************/

/* Dummy type to describe the dynamic array of Ipv6Ssid */
typedef struct Ipv6Ssid_dyn_arr
{
    Ipv6Ssid array[1];
} Ipv6Ssid_dyn_arr_t;

/* Member descriptors for the dynamic array */
static const marshal_member_descriptor_t mmd_Ipv6Ssid_dyn_arr_t[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(Ipv6Ssid_dyn_arr_t, Ipv6Ssid, array, 1),
};

/* Since SsidData_dyn_arr_t doesn't know the length of its array (only its parent
   knows) a callback is not set. The parent's array_elements callback
   will be called instead. */
const marshal_type_descriptor_dynamic_t mtd_Ipv6Ssid_dyn_arr_t =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_DYNAMIC_ARRAY(Ipv6Ssid_dyn_arr_t,
                                                       mmd_Ipv6Ssid_dyn_arr_t,
                                                       NULL);

/********************************************************************
 * Marshal Descriptors for Ipv6Address
 ********************************************************************/

static uint32 getNumIpv6Ssids(const void *parent,
                                  const marshal_member_descriptor_t *memberDescriptor,
                                  uint32 arrayElement)
{
    const Ipv6Address *obj = parent;
    uint32 len = 0;

    PanicFalse(obj && memberDescriptor);
    PanicFalse(arrayElement == 0);
    PanicFalse(memberDescriptor->offset == offsetof(Ipv6Address, ipv6Ssids));

    len = obj->numSsids;

    return len;
}

static const marshal_member_descriptor_t mmd_Ipv6Address[] =
{
    MAKE_MARSHAL_MEMBER(Ipv6Address, uint8, numSsids),
    MAKE_MARSHAL_MEMBER_POINTER(Ipv6Address, Ipv6Ssid_dyn_arr_t, ipv6Ssids),
};

static const marshal_type_descriptor_dynamic_t mtd_Ipv6Address =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_PTR_TO_DYNAMIC_ARRAY(
                Ipv6Address,
            mmd_Ipv6Address,
            getNumIpv6Ssids
);

/********************************************************************
 * Marshal Descriptors for ConnectedDevicesData
 ********************************************************************/

static const marshal_member_descriptor_t mmd_ConnectedDevicesData[] =
{
    MAKE_MARSHAL_MEMBER(ConnectedDevicesData, uint8,  transport),
    MAKE_MARSHAL_MEMBER(ConnectedDevicesData, uint16, primaryFrequency),
};

static const marshal_type_descriptor_t mtd_ConnectedDevicesData =
        MAKE_MARSHAL_TYPE_DEFINITION(
        ConnectedDevicesData,
        mmd_ConnectedDevicesData
);

/********************************************************************
 * Marshal Descriptors for ConnectedDevicesData_dyn_arr_t (used in ConnectedDevices)
 ********************************************************************/

/* Dummy type to describe the dynamic array of ConnectedDevicesData */
typedef struct ConnectedDevicesData_dyn_arr_t
{
    ConnectedDevicesData array[1];
} ConnectedDevicesData_dyn_arr_t;

/* Member descriptors for the dynamic array */
static const marshal_member_descriptor_t mmd_ConnectedDevicesData_dyn_arr_t[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(ConnectedDevicesData_dyn_arr_t, ConnectedDevicesData, array, 1),
};

/* Since ConnectedDevicesData_dyn_arr_t doesn't know the length of its array (only its parent
   knows) a callback is not set. The parent's array_elements callback
   will be called instead. */
const marshal_type_descriptor_dynamic_t mtd_ConnectedDevicesData_dyn_arr_t =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_DYNAMIC_ARRAY(ConnectedDevicesData_dyn_arr_t,
                                                       mmd_ConnectedDevicesData_dyn_arr_t,
                                                       NULL);

/********************************************************************
 * Marshal Descriptors for ConnectedDevices
 ********************************************************************/

static uint32 getNumConnectedDevices(const void *parent,
                                  const marshal_member_descriptor_t *memberDescriptor,
                                  uint32 arrayElement)
{
    const ConnectedDevices *obj = parent;
    uint32 len = 0;

    PanicFalse(obj && memberDescriptor);
    PanicFalse(arrayElement == 0);
    PanicFalse(memberDescriptor->offset == offsetof(ConnectedDevices, connectedDevice));

    len = obj->numDevices;

    return len;
}

static const marshal_member_descriptor_t mmd_ConnectedDevices[] =
{
    MAKE_MARSHAL_MEMBER(ConnectedDevices, uint8, numDevices),
    MAKE_MARSHAL_MEMBER_POINTER(ConnectedDevices, ConnectedDevicesData_dyn_arr_t, connectedDevice),
};

static const marshal_type_descriptor_dynamic_t mtd_ConnectedDevices =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_PTR_TO_DYNAMIC_ARRAY(
            ConnectedDevices,
            mmd_ConnectedDevices,
            getNumConnectedDevices
);

/********************************************************************
 * Marshal Descriptors for MacAddressData
 ********************************************************************/

static const marshal_member_descriptor_t mmd_MacAddressData[] =
{
    MAKE_MARSHAL_MEMBER(MacAddressData, uint32,  audioLocation),
    MAKE_MARSHAL_MEMBER_ARRAY(MacAddressData, uint8, macAddress, 6),
};

static const marshal_type_descriptor_t mtd_MacAddressData =
        MAKE_MARSHAL_TYPE_DEFINITION(
        MacAddressData,
        mmd_MacAddressData
);

/********************************************************************
 * Marshal Descriptors for MacAddressData_dyn_arr_t (used in MacAddress)
 ********************************************************************/

/* Dummy type to describe the dynamic array of MacAddressData */
typedef struct MacAddressData_dyn_arr_t
{
    MacAddressData array[1];
} MacAddressData_dyn_arr_t;

/* Member descriptors for the dynamic array */
static const marshal_member_descriptor_t mmd_MacAddressData_dyn_arr_t[] =
{
    MAKE_MARSHAL_MEMBER_ARRAY(MacAddressData_dyn_arr_t, MacAddressData, array, 1),
};

/* Since MacAddressData_dyn_arr_t doesn't know the length of its array (only its parent
   knows) a callback is not set. The parent's array_elements callback
   will be called instead. */
const marshal_type_descriptor_dynamic_t mtd_MacAddressData_dyn_arr_t =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_DYNAMIC_ARRAY(MacAddressData_dyn_arr_t,
                                                       mmd_MacAddressData_dyn_arr_t,
                                                       NULL);

/********************************************************************
 * Marshal Descriptors for MacAddress
 ********************************************************************/

static uint32 getNumMacAddresses(const void *parent,
                                  const marshal_member_descriptor_t *memberDescriptor,
                                  uint32 arrayElement)
{
    const MacAddress *obj = parent;
    uint32 len = 0;

    PanicFalse(obj && memberDescriptor);
    PanicFalse(arrayElement == 0);
    PanicFalse(memberDescriptor->offset == offsetof(MacAddress, macAddressData));

    len = obj->numMacAddresses;

    return len;
}

static const marshal_member_descriptor_t mmd_MacAddress[] =
{
    MAKE_MARSHAL_MEMBER(MacAddress, uint8, numMacAddresses),
    MAKE_MARSHAL_MEMBER_POINTER(MacAddress, MacAddressData_dyn_arr_t, macAddressData),
};

static const marshal_type_descriptor_dynamic_t mtd_MacAddress =
        MAKE_MARSHAL_TYPE_DEFINITION_HAS_PTR_TO_DYNAMIC_ARRAY(
            MacAddress,
            mmd_MacAddress,
            getNumMacAddresses
);

/********************************************************************
 * Marshal Descriptors for TwtConfiguration
 ********************************************************************/

static const marshal_member_descriptor_t mmd_TwtConfiguration[] =
{
    MAKE_MARSHAL_MEMBER(TwtConfiguration, uint8,  setupId),
    MAKE_MARSHAL_MEMBER(TwtConfiguration, uint32, desiredWakeDuration),
    MAKE_MARSHAL_MEMBER(TwtConfiguration, uint32, desiredWakeInterval),
    MAKE_MARSHAL_MEMBER_ARRAY(TwtConfiguration, uint32, desiredWakeTsfLeft, 2),
    MAKE_MARSHAL_MEMBER(TwtConfiguration, uint32, desiredWakeTsfRightOffset),
    MAKE_MARSHAL_MEMBER(TwtConfiguration, uint8,  bitfield),
};

static const marshal_type_descriptor_t mtd_TwtConfiguration =
        MAKE_MARSHAL_TYPE_DEFINITION(
        TwtConfiguration,
        mmd_TwtConfiguration
);

/********************************************************************
 * Marshal Descriptors for GattXpanHandoverData
 ********************************************************************/
static const marshal_member_descriptor_t mmd_GattXpanHandoverData[] =
{
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, StoredSsid,  storedSsid),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, Ipv4Address,  ipv4Address),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, Ipv6Address,  ipv6Address),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, uint16, l2capTcpPort),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, uint16, udpPort),
        MAKE_MARSHAL_MEMBER_ARRAY(GattXpanHandoverData, uint8, mDnsSrvUuid, 16),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, ConnectedDevices, connectedDevices),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, uint8, bearerPreference),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, MacAddress, macAddress),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, uint8, requestedSapPowerState),
        MAKE_MARSHAL_MEMBER_ARRAY(GattXpanHandoverData, uint8, features, 8),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, uint8, numDevices),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, uint8, periodicity),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, uint32, twtStatus),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, uint32, sapConnectionStatus),
        /* The following fields are connection (client) specific */
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, GattXpanServerConfig, clientConfig),
        MAKE_MARSHAL_MEMBER(GattXpanHandoverData, TwtConfiguration, twtConfiguration),

        /* ConnectionId              cid;                       <-- NOT handed over  */
        /* ClearToSend               clearToSend;               <-- NOT handed over. */
        /* XpanAudioBearerSwitchResponse audioBearerStatus;     <-- NOT handed over. Should this be set to 'Fail' (equivalent to 'not ready') before Handover? And then set correctly on new primary? */
};

static const marshal_type_descriptor_t mtd_GattXpanHandoverData =
        MAKE_MARSHAL_TYPE_DEFINITION(GattXpanHandoverData,
                                     mmd_GattXpanHandoverData);

/********************************************************************
 * Array of pointers to mtd_* structures
 ********************************************************************/

/* Use xmacro to expand type table as array of type descriptors */
#define EXPAND_AS_TYPE_DEFINITION(type) (const marshal_type_descriptor_t *) &mtd_##type,
const marshal_type_descriptor_t * const  mtdXpanConnection[] =
{
    COMMON_MARSHAL_TYPES_TABLE(EXPAND_AS_TYPE_DEFINITION)
    COMMON_DYN_MARSHAL_TYPES_TABLE(EXPAND_AS_TYPE_DEFINITION)
    XPAN_MARSHAL_TYPES_TABLE(EXPAND_AS_TYPE_DEFINITION)
};
#undef EXPAND_AS_TYPE_DEFINITION

/****************************** END of Desc code ******************************/
static void xpanServerHandoverMgrFreeStoredSsidData(StoredSsid* storedSsid)
{
    int i;
    /*
     * StoredSsid | --> numSsid
     *            | --> ssid[numSsid] |--> ssidLength
     *                                |--> ssid[ssidLength]
     */
    if (storedSsid->numSsid != 0)
    {
        for (i = 0; i < storedSsid->numSsid; ++i)
        {
            if (storedSsid->ssid[i].ssidLength)
                pfree(storedSsid->ssid[i].ssid);
        }
        pfree(storedSsid->ssid);
    }
}
static void xpanServerHandoverMgrFreeIpv4Address(Ipv4Address* ipv4Address)
{
    int i;
    /*
     * Ipv4Address | --> numSsids
     *             | --> ipv4Ssids[numSsids] |--> numIpv4Addresses
     *                                       |--> ipv4Addresses[numIpv4Addresses]
     *                                       |--> ipv4Ssid.ssidLength
     *                                       |--> ipv4Ssid.ssid[ipv4Ssid.ssidLength]
     */
    if (ipv4Address->numSsids != 0)
    {
        for (i = 0; i < ipv4Address->numSsids; ++i)
        {
            if (ipv4Address->ipv4Ssids[i].numIpv4Addresses != 0)
            {
                pfree(ipv4Address->ipv4Ssids[i].ipv4Addresses);
            }
            if(ipv4Address->ipv4Ssids[i].ipv4Ssid.ssidLength != 0)
            {
                pfree(ipv4Address->ipv4Ssids[i].ipv4Ssid.ssid);
            }
        }
        pfree(ipv4Address->ipv4Ssids);
    }
}
static void xpanServerHandoverMgrFreeIpv6Address(Ipv6Address* ipv6Address)
{
    int i;
    /*
     * Ipv6Address | --> numSsids
     *             | --> ipv6Ssids[numSsids] |--> numIpv6Addresses
     *                                       |--> ipv6Addresses[numIpv6Addresses]
     *                                       |--> ipv6Ssid.ssidLength
     *                                       |--> ipv6Ssid.ssid[ipv6Ssid.ssidLength]
     */
    if (ipv6Address->numSsids != 0)
    {
        for (i = 0; i < ipv6Address->numSsids; ++i)
        {
            if (ipv6Address->ipv6Ssids[i].numIpv6Addresses != 0)
            {
                pfree(ipv6Address->ipv6Ssids[i].ipv6Addresses);
            }
            if(ipv6Address->ipv6Ssids[i].ipv6Ssid.ssidLength != 0)
            {
                pfree(ipv6Address->ipv6Ssids[i].ipv6Ssid.ssid);
            }
        }
        pfree(ipv6Address->ipv6Ssids);
    }
}
static void xpanServerHandoverMgrFreeConnectedDevices(ConnectedDevices* connectedDevices)
{
    /*
     * ConnectedDevices | --> numDevices
     *                  | --> connectedDevice[numDevices]
     */
    if (connectedDevices->numDevices != 0)
        pfree(connectedDevices->connectedDevice);
}
static void xpanServerHandoverMgrFreeMacAddresses(MacAddress* macAddresses)
{
    /*
     * MacAddress | --> numMacAddresses
     *            | --> macAddressData[numMacAddresses]
     */
    if (macAddresses->numMacAddresses != 0)
        pfree(macAddresses->macAddressData);
}

static void xpanServerHandoverMgrReadClientData(XpanHandoverMgr* handoverMgr,
                                                GattXpanClientData* client)
{
    handoverMgr->handoverData->twtConfiguration = client->twtConfig;
    handoverMgr->handoverData->clientConfig = client->clientCfg;
}

static void xpanServerHandoverMgrWriteClientData(GattXpanHandoverData* handoverData,
                                                GattXpanClientData* client)
{
    client->cid = handoverData->cid;
    client->twtConfig = handoverData->twtConfiguration;
    client->clientCfg = handoverData->clientConfig;
}

static void xpanServerHandoverMgrReadServerData(XpanHandoverMgr* handoverMgr,
                                                GattXpanData* xpanServerData)
{
    handoverMgr->handoverData->storedSsid             = xpanServerData->storedSsid;
    handoverMgr->handoverData->ipv4Address            = xpanServerData->ipv4Address;
    handoverMgr->handoverData->ipv6Address            = xpanServerData->ipv6Address;
    handoverMgr->handoverData->l2capTcpPort           = xpanServerData->l2capTcpPort;
    handoverMgr->handoverData->udpPort                = xpanServerData->udpPort;
    SynMemCpyS(handoverMgr->handoverData->mDnsSrvUuid, 16, xpanServerData->mDnsSrvUuid, 16);
    handoverMgr->handoverData->connectedDevices       = xpanServerData->connectedDevices;
    handoverMgr->handoverData->bearerPreference       = xpanServerData->bearerPreference;
    handoverMgr->handoverData->macAddress             = xpanServerData->macAddress;
    handoverMgr->handoverData->requestedSapPowerState = xpanServerData->requestedSapPowerState;
    SynMemCpyS(handoverMgr->handoverData->features, 8,     xpanServerData->features, 8);
    handoverMgr->handoverData->numDevices             = xpanServerData->numDevices;
    handoverMgr->handoverData->periodicity            = xpanServerData->periodicity;
    handoverMgr->handoverData->twtStatus              = xpanServerData->twtStatus;
    handoverMgr->handoverData->sapConnectionStatus    = xpanServerData->sapConnectionStatus;
}

static void xpanServerHandoverMgrWriteServerData(GattXpanHandoverData* handoverData,
                                                GattXpanData* xpanServerData)
{
    xpanServerHandoverMgrFreeStoredSsidData(&xpanServerData->storedSsid);
    xpanServerData->storedSsid = handoverData->storedSsid;
    xpanServerHandoverMgrFreeIpv4Address(&xpanServerData->ipv4Address);
    xpanServerData->ipv4Address             = handoverData->ipv4Address;
    xpanServerHandoverMgrFreeIpv6Address(&xpanServerData->ipv6Address);
    xpanServerData->ipv6Address             = handoverData->ipv6Address;
    xpanServerData->l2capTcpPort            = handoverData->l2capTcpPort;
    xpanServerData->udpPort                 = handoverData->udpPort;
    SynMemCpyS(xpanServerData->mDnsSrvUuid, 16, handoverData->mDnsSrvUuid, 16);
    xpanServerHandoverMgrFreeConnectedDevices(&xpanServerData->connectedDevices);
    xpanServerData->connectedDevices        = handoverData->connectedDevices;
    xpanServerData->bearerPreference        = handoverData->bearerPreference;
    xpanServerHandoverMgrFreeMacAddresses(&xpanServerData->macAddress);
    xpanServerData->macAddress              = handoverData->macAddress;
    xpanServerData->requestedSapPowerState  = handoverData->requestedSapPowerState;
    SynMemCpyS(xpanServerData->features, 8, handoverData->features, 8);
    xpanServerData->numDevices              = handoverData->numDevices;
    xpanServerData->periodicity             = handoverData->periodicity;
    xpanServerData->twtStatus               = handoverData->twtStatus;
    xpanServerData->sapConnectionStatus     = handoverData->sapConnectionStatus;
}

static bool xpanServerHandoverMgrMarshal(XpanHandoverMgr* handoverMgr,
                                         GattXpanData* xpanServerData,
                                         GattXpanClientData* xpanClientData,
                                         uint8 *buf,
                                         uint16 length,
                                         uint16 *written)
{
    bool marshalled;

    if (!handoverMgr->marshallerInitialised)
    {
        handoverMgr->marshaller = MarshalInit(mtdXpanConnection, XPAN_MARSHAL_OBJ_TYPE_COUNT);
        handoverMgr->marshallerInitialised = TRUE;
        handoverMgr->handoverData = zpnew(GattXpanHandoverData);
        xpanServerHandoverMgrReadClientData(handoverMgr, xpanClientData);
        xpanServerHandoverMgrReadServerData(handoverMgr, xpanServerData);
    }

    MarshalSetBuffer(handoverMgr->marshaller, (void *) buf, length);

    marshalled = Marshal(handoverMgr->marshaller, handoverMgr->handoverData, MARSHAL_TYPE(GattXpanHandoverData));

    *written = MarshalProduced(handoverMgr->marshaller);

    if (marshalled)
    {
        MarshalDestroy(handoverMgr->marshaller, /*free_all_objects*/FALSE);
        handoverMgr->marshallerInitialised = FALSE;

        /* This is NOT deleted by mashalDestroy*/
        free(handoverMgr->handoverData);
        handoverMgr->handoverData = NULL;

    }
    return marshalled;
}

/****************************************************************************
NAME
    gattXpanServerHandoverMarshal

DESCRIPTION
    Marshal the data associated with the XPAN Server

RETURNS
    bool TRUE if XPAN module marshaling completed successfully, or if it cannot complete and must be abandoned
         (e.g. if the cid is unrecognised).
         FALSE if marshaling is ongoing and we need more buffers (provided in subsequent calls to gattAscsMarshal() )
         before marshaling can be completed.
*/
bool gattXpanServerHandoverMarshal(ServiceHandle serviceHandle,
                           ConnectionId cid,
                           uint8 *buf,
                           uint16 length,
                           uint16 *written)
{
    GattXpanServerData *xpan = (GattXpanServerData*)ServiceHandleGetInstanceData(serviceHandle);
    XpanClientDataElement *client;

    if (xpan == NULL)
    {
        GATT_XPAN_SERVER_PANIC("XPAN Server: Client not found");
    }

    /* It's a bit harsh, but this panics if the client isn't found, the behaviour may change so we'll check 'client' anyway */
    client = xpanFindClient(&xpan->data.connectedClients, cid);

    if (client)
    {
        if (xpan->handoverMgr == NULL)
        {
            xpan->handoverMgr = zpnew(XpanHandoverMgr); /* counters, bools etc. are initialised to zero */
        }
        return xpanServerHandoverMgrMarshal(xpan->handoverMgr, &xpan->data, &client->clientData, buf, length, written);
    }
    else
    {
        /* Connection not found, nothing to marshal */
        *written = 0;
        return TRUE;
    }
}

static bool xpanServerHandoverMgrUnmarshal(XpanHandoverMgr* handoverMgr,
                                           ConnectionId cid,
                                           const uint8 *buf,
                                           uint16 length,
                                           uint16 *consumed)
{
    marshal_type_t unmarshalledType;
    bool unMarshalled;

    if (!handoverMgr->unMarshallerInitialised)
    {
        handoverMgr->unMarshaller = UnmarshalInit(mtdXpanConnection, XPAN_MARSHAL_OBJ_TYPE_COUNT);
        handoverMgr->unMarshallerInitialised = TRUE;
    }
    UnmarshalSetBuffer(handoverMgr->unMarshaller, (void *) buf, length);

    unMarshalled = Unmarshal(handoverMgr->unMarshaller, (void**)&handoverMgr->handoverData, &unmarshalledType);

    *consumed = UnmarshalConsumed(handoverMgr->unMarshaller);

    if (unMarshalled)
    {
        PanicFalse(unmarshalledType == MARSHAL_TYPE(GattXpanHandoverData));
        PanicNull(handoverMgr->handoverData);

        handoverMgr->handoverData->cid = cid;
        handoverMgr->handoverConnection[handoverMgr->numHandoverConnections++] = handoverMgr->handoverData;

        handoverMgr->handoverData = NULL;
        UnmarshalDestroy(handoverMgr->unMarshaller, /*free_all_objects*/FALSE); /* The GattXpanHandoverData* is freed explicitly after hand over is completed */
        handoverMgr->unMarshallerInitialised = FALSE;
    }
    return unMarshalled;
}

bool gattXpanServerHandoverUnmarshal(ServiceHandle serviceHandle,
                             ConnectionId cid,
                             const uint8 *buf,
                             uint16 length,
                             uint16 *consumed)
{
    GattXpanServerData *xpan = (GattXpanServerData*)ServiceHandleGetInstanceData(serviceHandle);

    if (xpan == NULL)
    {
        GATT_XPAN_SERVER_PANIC("XPAN Server: Client not found");
    }
    if (xpan->handoverMgr == NULL)
    {
        xpan->handoverMgr = zpnew(XpanHandoverMgr); /* counters, bools, numHandoverConnections etc. are initialised to zero */
    }
    return xpanServerHandoverMgrUnmarshal(xpan->handoverMgr, cid, buf, length, consumed);
}

static void xpanHandoverCommitConnection(XpanHandoverMgr* handoverMgr, GattXpanData* xpanData, ConnectionId cid)
{
    bool moveConnectionToLowerIndex = FALSE;
    int connIdx;
    const uint8 numHandoverConnections = MIN(handoverMgr->numHandoverConnections, GATT_XPAN_NUM_CONNECTIONS_MAX);
    XpanClientDataElement *client;

    for (connIdx = 0; connIdx < numHandoverConnections; ++connIdx)
    {
        if (moveConnectionToLowerIndex)
        {
            handoverMgr->handoverConnection[connIdx - 1] = handoverMgr->handoverConnection[connIdx];
        }
        else
        {
            if (handoverMgr->handoverConnection[connIdx]->cid == cid)
            {
                client = xpanAddClient(&xpanData->connectedClients , cid);

                xpanServerHandoverMgrWriteServerData(handoverMgr->handoverConnection[connIdx], xpanData);
                xpanServerHandoverMgrWriteClientData(handoverMgr->handoverConnection[connIdx], &client->clientData);


                free(handoverMgr->handoverConnection[connIdx]);
                handoverMgr->handoverConnection[connIdx] = NULL;

                moveConnectionToLowerIndex = TRUE;
                handoverMgr->numHandoverConnections--;
            }
        }
    }
}

static void xpanServerHandoverMgrCommit(XpanHandoverMgr* handoverMgr,
                                        GattXpanData* xpanServerData,
                                        ConnectionId cid,
                                        const bool newPrimary)
{
    if (newPrimary)
    {
        /* This is the new primary EB */
        xpanHandoverCommitConnection(handoverMgr, xpanServerData, cid);
    }
    else
    {
        XpanClientDataElement * clientDataElement;
        /* This is the new secondary EB */

        /* It's a bit harsh, but this panics if the client isn't found, the behaviour may change so we'll check the return value anyway */
        clientDataElement = xpanFindClient(&xpanServerData->connectedClients, cid);
        if (clientDataElement)
        {
            XPAN_REMOVE_CLIENT(xpanServerData->connectedClients, clientDataElement);
        }
    }
}

void gattXpanServerHandoverCommit(ServiceHandle serviceHandle, ConnectionId cid, const bool newPrimary)
{

    GattXpanServerData *xpan = (GattXpanServerData*)ServiceHandleGetInstanceData(serviceHandle);

    if (xpan == NULL)
    {
        GATT_XPAN_SERVER_PANIC("XPAN Server: Client not found");
    }

    if (xpan->handoverMgr != NULL)
    {

        xpanServerHandoverMgrCommit(xpan->handoverMgr, &xpan->data, cid, newPrimary);
    }
    else
    {
        GATT_XPAN_SERVER_ERROR("Called gattXpanServerHandoverCommit but no handoverMgr allocated - has (un)marshal been called and no previous call to Complete() or Abort()?\n");
    }
}

static void xpanServerHandoverMgrComplete(XpanHandoverMgr* handoverMgr)
{
    int connIdx,i;
    if (handoverMgr->marshallerInitialised)
    {
        /* The Handover procedure has finished (failed to complete successfully
         * in this case), and the Marshaller has not been destroyed, it may
         * contain objects that have not been freed.
         */
        MarshalDestroy(handoverMgr->marshaller, /*free_all_objects*/FALSE);
        handoverMgr->marshallerInitialised = FALSE;
    }

    if (handoverMgr->unMarshallerInitialised)
    {
        /* The Handover procedure has finished (failed to complete successfully
         * in this case), and the UnMarshaller has not been destroyed, it still
         * contains objects that have not been freed.
         *
         * Fortunately, the unmarshaller will not give any data to XPAN unless it
         * has successfully unmarshalled a complete client connection, at which point
         * the unmarshaller is destroyed. Since the unnmarshaller has *not* been
         * destroyed (handoverMgr->unMarshallerInitialised == TRUE) , it has
         * not given a client connection to XPAN, so passing 'TRUE' as the free_all_object
         * argument should prevent any memory leaks and should not cause any
         * 'double frees'.
         */
        UnmarshalDestroy(handoverMgr->unMarshaller, /*free_all_objects*/TRUE);
        handoverMgr->unMarshallerInitialised = FALSE;
    }

    const uint8 numHandoverConnections = MIN(handoverMgr->numHandoverConnections, GATT_XPAN_NUM_CONNECTIONS_MAX);
    
    for (connIdx = 0; connIdx < numHandoverConnections; ++connIdx)
    {
        if (handoverMgr->handoverConnection[connIdx] != NULL)
        {
            GATT_XPAN_SERVER_WARNING("Called xpanServerHandoverMgrComplete _before_ cid=0x%02x was committed.\n", handoverMgr->handoverConnection[connIdx]->cid);

            for(i = 0; i < handoverMgr->handoverConnection[connIdx]->storedSsid.numSsid; i++)
            {
                pfree(handoverMgr->handoverConnection[connIdx]->storedSsid.ssid[i].ssid);
            }
            pfree(handoverMgr->handoverConnection[connIdx]->storedSsid.ssid);

            for(i = 0; i < handoverMgr->handoverConnection[connIdx]->ipv4Address.numSsids; i++)
            {
                pfree(handoverMgr->handoverConnection[connIdx]->ipv4Address.ipv4Ssids[i].ipv4Ssid.ssid);
                pfree(handoverMgr->handoverConnection[connIdx]->ipv4Address.ipv4Ssids[i].ipv4Addresses);
            }
            pfree(handoverMgr->handoverConnection[connIdx]->ipv4Address.ipv4Ssids);

            for(i = 0; i < handoverMgr->handoverConnection[connIdx]->ipv6Address.numSsids; i++)
            {
                pfree(handoverMgr->handoverConnection[connIdx]->ipv6Address.ipv6Ssids[i].ipv6Ssid.ssid);
                pfree(handoverMgr->handoverConnection[connIdx]->ipv6Address.ipv6Ssids[i].ipv6Addresses);
            }
            pfree(handoverMgr->handoverConnection[connIdx]->ipv6Address.ipv6Ssids);
            pfree(handoverMgr->handoverConnection[connIdx]->connectedDevices.connectedDevice);
            pfree(handoverMgr->handoverConnection[connIdx]->macAddress.macAddressData);

            free(handoverMgr->handoverConnection[connIdx]);
            handoverMgr->handoverConnection[connIdx] = NULL;
        }
    }
    handoverMgr->numHandoverConnections = 0;
}

void XpanServerHandoverMgrCleanup(ServiceHandle serviceHandle)
{
    GattXpanServerData *xpan = (GattXpanServerData*)ServiceHandleGetInstanceData(serviceHandle);

    if (xpan == NULL)
    {
        GATT_XPAN_SERVER_PANIC("XPAN Server: Client not found");
    }
    /*
     * At the moment there is no difference between handling a hand over 'abort' or a hand over 'complete':
     * they both ensure any 'leftover' hand over connections are freed.
     */
    if (xpan->handoverMgr != NULL)
    {
        xpanServerHandoverMgrComplete(xpan->handoverMgr);
        free(xpan->handoverMgr);
        xpan->handoverMgr = NULL;
    }
    else
    {
        GATT_XPAN_SERVER_ERROR("Called XpanServerHandoverMgrCleanup but no handoverMgr allocated - has Complete() or Abort() been called and no previous call to (un)marshal?\n");
    }
}

void gattXpanServerHandoverAbort(ServiceHandle serviceHandle)
{
    /*
     * At the moment there is no difference between handling a hand over 'abort' or a hand over 'complete':
     * they both ensure any 'leftover' hand over connections are freed.
     */
    XpanServerHandoverMgrCleanup(serviceHandle);
}

void gattXpanServerHandoverComplete(ServiceHandle serviceHandle, const bool newPrimary )
{
    (void)newPrimary;
    /*
     * At the moment there is no difference between handling a hand over 'abort' or a hand over 'complete':
     * they both ensure any 'leftover' hand over connections are freed.
     */

    XpanServerHandoverMgrCleanup(serviceHandle);
}

bool gattXpanServerHandoverVeto(ServiceHandle serviceHandle)
{
    GattXpanServerData *xpan = (GattXpanServerData*)ServiceHandleGetInstanceData(serviceHandle);

    if (xpan == NULL)
    {
        /* Handover cannot proceed if we do not have an XPAN instance */
        GATT_XPAN_SERVER_PANIC("XPAN Server: Client not found");
    }

    return FALSE;
}

#endif /* EXCLUDE_GATT_XPAN_SERVER_MODULE */


